﻿#region License

// PentaBiz - Sustainable Software Development Framework Copyright (C) 2013 Zoltán Csizmazia
// 
// This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

#endregion

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
using System.Threading.Tasks;
using PentaBiz;
using PentaBiz.Cloud.Services;
using PentaBiz.Cloud.Services.DynamicService;
using PentaBiz.Cloud.Services.MetaService;
using PentaBiz.Cloud.Services.QueryService;

namespace Cloud.Services.Hosting
{
    public class GenericServiceHostManager : IDisposable, ICloudServiceHostManager
    {
        private readonly List<ICloudServiceHost> services = new List<ICloudServiceHost>();
        private EndpointMode _endpointMode;
        private bool disposed;
        private DynamicServiceManager dynamicServiceManager;

        public GenericServiceHostManager()
        {
            AppDomain.CurrentDomain.ProcessExit += OnCurrentDomainProcessExit;
        }


        //DynamicServiceManager dynamicServiceManager = new DynamicServiceManager();

        public EndpointMode EndpointMode
        {
            get { return _endpointMode; }
        }

        public IReadOnlyCollection<ICloudServiceHost> CloudServiceHosts
        {
            get { return services.AsReadOnly(); }
        }

        public void Start(EndpointMode endpointMode)
        {
            _endpointMode = endpointMode;
            Start();
        }

        public void Start()
        {
            //start meta query service
            //start meta command service
            //start dynamicservice

            dynamicServiceManager = new DynamicServiceManager();
            services.Add(new MetaDbQueryServiceHost());
            services.Add(new GenericWcfServiceHost<MetaCommandService>());
            services.Add(new GenericWcfServiceHost<DynamicServiceManager>(dynamicServiceManager));


            services.ToArray().AsParallel()
                    .ForAll(a =>
                        {
                            try
                            {
                                a.Start(EndpointMode);
                            }
                            catch (Exception)
                            {
                                lock (services)
                                {
                                    services.Remove(a);
                                }
                                throw;
                            }
                        });


            //todo: make this configurable
            //dynamicServiceManager.DeployAllMetaChangeSets();
        }

        public void Stop()
        {
            services.AsParallel().ForAll(a => a.Stop());
            services.Clear();
        }

        public void Restart()
        {
            Stop();
            Start();
        }


        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        ///     Called when [current domain process exit].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">
        ///     The <see cref="EventArgs" /> instance containing the event data.
        /// </param>
        private void OnCurrentDomainProcessExit(object sender, EventArgs e)
        {
            //gracefully stop the controlled service hosts on process exit
            Stop();
        }

        ~GenericServiceHostManager()
        {
            Dispose(false);
        }

        private void Dispose(bool disposing)
        {
            if (disposed)
                return;

            if (disposing)
            {
                Stop();
                dynamicServiceManager.Dispose();
            }

            disposed = true;
        }
    }

    //public class GenericServiceDomain : MarshalByRefObject
    //{
    //    //assembly loader and wcf service controller
    //    //loads the assembly
    //    //runs the wcf services inside.
    //}

    //public class GenericServiceHostSettings : ConfigurationSection
    //{
    //    private static Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

    //    private static GenericServiceHostSettings settings
    // = config.GetSection("GenericServiceHostSettings") as GenericServiceHostSettings;


    //    public bool IsDirty { get; private set; }
    //    public static GenericServiceHostSettings Settings
    //    {
    //        get
    //        {

    //            if (settings == null)
    //            {
    //                settings = new GenericServiceHostSettings();
    //                config.Sections.Add("GenericServiceHostSettings", settings);
    //                config.Save();
    //            }
    //            return settings;
    //        }
    //    }

    //    [ConfigurationProperty("IsEnabled", DefaultValue = "true", IsRequired = false)]
    //    public bool IsEnabled
    //    {
    //        get
    //        {
    //            return (bool)this["IsEnabled"];
    //        }
    //        set
    //        {
    //            this["IsEnabled"] = value;
    //            IsDirty = true;
    //        }
    //    }
    //    [ConfigurationProperty("ServiceDirectory", DefaultValue = "HostedServices", IsRequired = false)]
    //    public string ServiceDirectory
    //    {
    //        get
    //        {
    //            return (string)this["ServiceDirectory"];
    //        }
    //        set
    //        {
    //            this["ServiceDirectory"] = value;
    //            IsDirty = true;
    //        }
    //    }

    //    public void Save()
    //    {
    //        if (IsDirty)
    //            config.Save();
    //        IsDirty = false;
    //    }
    //}
}